热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

定子|小节_flutter开发仿抖音首页面上下滑动切换播放视频效果

篇首语:本文由编程笔记#小编为大家整理,主要介绍了flutter开发仿抖音首页面上下滑动切换播放视频效果相关的知识,希望对你有一定的参考价值。题记

篇首语:本文由编程笔记#小编为大家整理,主要介绍了flutter开发仿抖音首页面上下滑动切换播放视频效果相关的知识,希望对你有一定的参考价值。


题记
—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天。

-----【视频教程 感兴趣的伙伴可以瞅瞅】





本小节讲述:
1 VideoPlayer 视频播放组件使用
2 VideoPlayerController 的使用分析
3 FutureBuilder 的使用分析
4 PageView构建上下滑动的整屏切换页面
5 TabBar 与 TabBarView 构建左右滑动切换的页面



1 首先我们来实现页面的主体部分

通过 TabBar 与 TabBarView 实现左右切换的页面


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MainFind3Page extends StatefulWidget
@override
State<StatefulWidget> createState()
return MainFindPage3State();


class MainFindPage3State extends State with SingleTickerProviderStateMixin

List<String> tabTextList &#61; ["关注", "推荐"];
List<Tab> tabWidgetList &#61; [];
TabController tabController;
&#64;override
void initState()
super.initState();
for (var value in tabTextList)
tabWidgetList.add(Tab(
text: "$value",
));

tabController &#61; new TabController(length: tabTextList.length, vsync: this);

&#64;override
Widget build(BuildContext context)
return buildRootBody();

Widget buildRootBody()
return Scaffold(
body: Stack(
children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: Container(
color: Colors.black,
),
),
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: buildTableViewWidget(),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
top: 54,
child: buildTabBarWidget(),
),
],
),
);

///构建 TabBarView
buildTableViewWidget()
return TabBarView(
controller: tabController,
children: tabTextList
.map((value) &#61;> Container(
alignment: Alignment.center,
child: Text("$value",style: TextStyle(color: Colors.white),),
))
.toList(),
);

///构建顶部标签部分
buildTabBarWidget()
return Container(
///对齐在顶部中间
alignment: Alignment.topCenter,
child: TabBar(
controller: tabController,
tabs: tabWidgetList,
///指示器的颜色
indicatorColor: Colors.white,
///指示器的高度
indicatorWeight: 2.0,
isScrollable: true,
///指示器的宽度与文字对齐
indicatorSize: TabBarIndicatorSize.label,
),
);


在这里是通过 帧布局 将 TabBar 与 TabBarView 叠在一起的。
效果如下


2 通过 PageView 来实现上下整屏切换效果

文章《flutter跨平台开发一点一滴分析系列文章》中 1.3.3 有记录 PageView 的使用案例

我们将上述 【构建 TabBarView】 处代码替换&#xff0c;使用 PageView 来构建 上下整屏页面切换效果


///构建 TabBarView
buildTableViewWidget()
return TabBarView(
controller: tabController,
children: tabTextList
.map((value) &#61;> buildTableViewItemWidget(value))
.toList(),
);

/// 用来创建上下滑动的页面
Widget buildTableViewItemWidget(String value)
List<VideoModel> list &#61;[];
if(value &#61;&#61; "推荐")
list&#61; videoList;
else
list &#61; videoList2;

return PageView.builder(
/// pageview中 子条目的个数
itemCount:list.length ,
/// 上下滑动
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context,int index)
VideoModel videoModel &#61; list[index];
return buildPageViewItemWidget(value,videoModel);
);

这里面用到了 videoList 与 videoList2&#xff0c;保存的数据模型,是在 initState函数中初始化的


///推荐模拟数据
List <VideoModel> videoList &#61;[];
///关注模拟数据
List <VideoModel> videoList2 &#61;[];
&#64;override
void initState()
super.initState();
...
///创建模拟数据
for (int i &#61; 0; i < 10; i&#43;&#43;)
VideoModel videoModel &#61; new VideoModel();
videoModel.videoName &#61; "推荐测试数据$i";
videoModel.pariseCount &#61; i * 22;
if (i % 3 &#61;&#61; 0)
videoModel.isAttention &#61; true;
videoModel.isLike &#61; true;
else
videoModel.isAttention &#61; false;
videoModel.isLike &#61; false;

videoModel.videoImag &#61;"";
videoModel.videoUrl &#61;"";
videoList.add(videoModel);

for (int i &#61; 0; i < 3; i&#43;&#43;)
VideoModel videoModel &#61; new VideoModel();
videoModel.videoName &#61; "关注测试数据$i";
videoModel.pariseCount &#61; i * 22;
videoModel.isAttention &#61; true;
if (i % 3 &#61;&#61; 0)
videoModel.isLike &#61; true;
else
videoModel.isLike &#61; false;

videoModel.videoImag &#61;"";
videoModel.videoUrl &#61;"";
videoList2.add(videoModel);


对于 VideoModel 来讲&#xff0c;就是我们保存视频信息的数据模型了


class VideoModel
///视频名称
String videoName &#61;&#39;&#39;;
///视频链接
String videoUrl &#61;&#39;&#39;;
///视频截图
String videoImag &#61;&#39;&#39;;
///是否关注
bool isAttention &#61;false;
///关注的个数
num attentCount &#61;0;
///是否喜欢
bool isLike &#61; false;
///点赞的个数
num pariseCount &#61; 0;
///分享的次数
num shareCount&#61;0;

在上述代码中我们也使用到了 buildPageViewItemWidget 函数&#xff0c;如下

buildPageViewItemWidget(String value, VideoModel videoModel)
return FindVideoItemPage(value,videoModel);

在这里直接构建 的 FindVideoItemPage &#xff0c;看如下 FindVideoItemPage 的定义


///播放视频的页面
class FindVideoItemPage extends StatefulWidget
String tabValue;
VideoModel videoModel;
FindVideoItemPage(this.tabValue, this.videoModel);
&#64;override
State<StatefulWidget> createState()
return FindVideoItemPageState();


class FindVideoItemPageState extends State<FindVideoItemPage>
///创建视频播放控制 器
VideoPlayerController videoPlayerController;
///控制更新视频加载初始化完成状态更新
Future videoPlayFuture;
&#64;override
void initState()
super.initState();
videoPlayerController &#61;
VideoPlayerController.network(widget.videoModel.videoUrl);
videoPlayFuture &#61; videoPlayerController.initialize().then((_)
///视频初始完成后
///调用播放
videoPlayerController.play();
setState(() );
);

&#64;override
Widget build(BuildContext context)
return Stack(
children: <Widget>[
///播放视频
buildVideoWidget(),
///控制播放视频按钮
buildControllWidget(),
///底部区域的视频介绍
buildBottmFlagWidget(),
///右侧的用户信息按钮区域
buildRightUserWidget(),
],
);

&#64;override
void dispose()
super.dispose();
videoPlayerController.dispose();


其实 FindVideoItemPage 就是我们 PageView 中构建的子视图了&#xff0c;我们可以看到 在 初始化函数 initState 中 创建了 VideoPlayerController&#xff0c;顾名思义 VideoPlayerController 是用来控制当前页面视频的播放的&#xff0c;在 dispose 中销毁 VideoPlayerController&#xff0c;这个也好理解&#xff0c;就是当前页面都释放掉了&#xff0c;播放的视频当然要停止播放了。

在这里这创建了一个 videoPlayFuture &#xff0c;是用来监听 VideoPlayerController 初始化状态的&#xff0c;结合 FutureBuilder 来实时更新页面 State,如在方法 buildVideoWidget() 中


///播放视频
buildVideoWidget()
return FutureBuilder(
future: videoPlayFuture,
builder: (BuildContext contex, value)
if (value.connectionState &#61;&#61; ConnectionState.done)
///点击事件
return InkWell(
onTap: ()
if (videoPlayerController.value.initialized)
/// 视频已初始化
if (videoPlayerController.value.isPlaying)
/// 正播放 --- 暂停
videoPlayerController.pause();
else
///暂停 ----播放
videoPlayerController.play();

setState(() );
else
///未初始化
videoPlayerController.initialize().then((_)
videoPlayerController.play();
setState(() );
);

,
///居中
child: Center(
/// AspectRatio 组件用来设定子组件宽高比
child: AspectRatio(
///设置视频的大小 宽高比。长宽比表示为宽高比。例如&#xff0c;16:9宽高比的值为16.0/9.0
aspectRatio: videoPlayerController.value.aspectRatio,
///播放视频的组件
child: VideoPlayer(videoPlayerController),
),
),
);
else
return Container(
alignment: Alignment.center,
///圆形加载进度
child: CircularProgressIndicator(),
);

,
);

FutureBuilder会依赖一个Future,对于FutureBuilder来讲

FutureBuilder(
this.future,
this.initialData,
&#64;required this.builder,
)

future ,FutureBuilder 中依赖的 Future ,通常是一个异步耗时任务,如这里的 videoPlayFuture 是指向 videoPlayerController 的初始化函数initialize()&#xff0c;这是一个异步的耗时操作,
builder ,Widget构建器,该构建器会在Future执行的不同阶段被多次调用&#xff0c;构建格式如下

Function (BuildContext context, AsyncSnapshot snapshot)
/**
* snapshot会包含当前异步任务的状态信息及结果信息 &#xff0c;
* 比如我们可以通过snapshot.connectionState获取异步任务的状态信息、
* 通过snapshot.hasError判断异步任务是否有错误等等
*/

而通过 snapshot.connectionState 获取的 ConnectionState 状态有以下值&#xff1a;

enum ConnectionState
/// 当前没有异步任务&#xff0c;比如[FutureBuilder]的[future]为null时
none,
/// 异步任务处于等待状态
waiting,
/// Stream处于激活状态&#xff08;流上已经有数据传递了&#xff09;&#xff0c;对于FutureBuilder没有该状态。
active,
/// 异步任务已经终止.
done,


3 通过 VideoPlayer 播放视频

使用 VideoPlayer&#xff0c;我们首先需要添加依赖

video_player: ^0.6.4

对于 VideoPlayer 来讲&#xff0c;它只接收一个 VideoPlayerController&#xff0c;我们可以通过 VideoPlayerController 来绑定要播放的视频地址

///网络链接
videoPlayerController &#61; VideoPlayerController.network(widget.videoModel.videoUrl);
///本地链接
VideoPlayerController videoPlayerController2 &#61; VideoPlayerController.asset(widget.videoModel.videoUrl);
///File形式的视频
VideoPlayerController videoPlayerController3 &#61; VideoPlayerController.file(File(widget.videoModel.videoUrl));

当 绑定了播放的地址后&#xff0c;可以VideoPlayerController来预加载初始化播放器

videoPlayerController.initialize().then((_)
///视频初始完成后
///调用播放
videoPlayerController.play();
setState(() );
);

对于 initialize() 方法来讲&#xff0c;这是一个异步的耗时操作.

VideoPlayerValue 记录了当前视频播放的一些状态信息

VideoPlayerValue videoPlayerValue &#61; videoPlayerController.value;
///是否初始化完成
bool initialized &#61; videoPlayerValue.initialized;
///是否正在播放
bool isPlaying &#61; videoPlayerValue.isPlaying;
///当前播放的视频的宽高比例
double aspectRatio &#61; videoPlayerValue.aspectRatio;
///当前视频是否缓存
bool isBuffer &#61; videoPlayerValue.isBuffering;
///当前视频是否循环
bool isLoop &#61; videoPlayerValue.isLooping;
///当前播放视频的总时长
Duration totalDuration &#61; videoPlayerValue.duration;
///当前播放视频的位置
Duration currentDuration &#61; videoPlayerValue.position;


在这里&#xff0c;我们通过 totalDuration 与 currentDuration 就可实现播放进度的进度条绘制。



完毕


推荐阅读
  • vue使用
    关键词: ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • MVC设计模式的介绍和演化过程
    本文介绍了MVC设计模式的基本概念和原理,以及在实际项目中的演化过程。通过分离视图、模型和控制器,实现了代码的解耦和重用,提高了项目的可维护性和可扩展性。详细讲解了分离视图、分离模型和分离控制器的具体步骤和规则,以及它们在项目中的应用。同时,还介绍了基础模型的封装和控制器的命名规则。该文章适合对MVC设计模式感兴趣的读者阅读和学习。 ... [详细]
  • SpringBoot简单日志配置
     在生产环境中,只打印error级别的错误,在测试环境中,可以调成debugapplication.properties文件##默认使用logbacklogging.level.r ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • Iwanttointegratesort,order,maxandoffsetinafindAllquery.Thefollowingworksfine:我想在fin ... [详细]
  • [转载]从零开始学习OpenGL ES之四 – 光效
    继续我们的iPhoneOpenGLES之旅,我们将讨论光效。目前,我们没有加入任何光效。幸运的是,OpenGL在没有设置光效的情况下仍然可 ... [详细]
  • Yii framwork 应用小窍门
    Yiiframework应用小窍门1.YiiFramework]如何获取当前controller的名称?下面语句就可以获取当前控制器的名称了!Php代码 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Django + Ansible 主机管理(有源码)
    本文给大家介绍如何利用DjangoAnsible进行Web项目管理。Django介绍一个可以使Web开发工作愉快并且高效的Web开发框架,能够以最小的代价构建和维护高 ... [详细]
author-avatar
benbowujixian
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有